package net.xiangcaowuyu.shiro.config;

import net.xiangcaowuyu.shiro.constant.AuthenConst;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.crazycake.shiro.RedisManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;
import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @author laughing
 * @date 2020/10/11
 * @site https://www.xiangcaowuyu.net
 */
@Configuration
public class ShiroConfig {

    /**
     * 自定义验证
     * @return
     */
    @Bean
    MyAuthenRealm myAuthenRealm() {
        MyAuthenRealm myAuthenRealm = new MyAuthenRealm();
//        myAuthenRealm.setCredentialsMatcher(hashedCredentialsMatcher());
        return myAuthenRealm;
    }

    @Resource
    ShiroProperty shiroProperty;

    /**
     * 权限管理，配置主要是Realm的管理认证
     *
     * @return
     */
    @Bean
    public SecurityManager securityManager() {
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
        defaultWebSecurityManager.setRealm(myAuthenRealm());
        // 自定义session管理 使用redis
        defaultWebSecurityManager.setSessionManager(sessionManager());
        return defaultWebSecurityManager;
    }

    /**
     * Filter工厂，设置对应的过滤条件和跳转条件
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean() {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager());
        Map<String, String> filterChainDefinitionMap = new HashMap<>();
        //登出
        filterChainDefinitionMap.put(shiroProperty.getUser().getUnauthorizedUrl(), "logout");
        //登录
        shiroFilterFactoryBean.setLoginUrl(shiroProperty.getUser().getLoginUrl());
        //首页
        shiroFilterFactoryBean.setSuccessUrl(shiroProperty.getUser().getIndexUrl());
        filterChainDefinitionMap.put("/", "anon");
        filterChainDefinitionMap.put("/static/**", "anon");
        filterChainDefinitionMap.put(shiroProperty.getUser().getLoginUrl(), "anon");
        filterChainDefinitionMap.put(shiroProperty.getUser().getUnauthorizedUrl(), "anon");
        filterChainDefinitionMap.put("/error", "anon");
        filterChainDefinitionMap.put("/**", "authc");
        LinkedHashMap<String, Filter> filtsMap = new LinkedHashMap<>();
        shiroFilterFactoryBean.setFilters(filtsMap);
        // 这里使用自定义的filter，禁止未登陆跳转
        filtsMap.put("authc", new ShiroFormAuthenticationFilter());
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }

    /**
     * 加入注解的使用，不加入这个注解不生效
     * @param securityManager
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }

    @Bean
    @ConditionalOnMissingBean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
        return defaultAdvisorAutoProxyCreator;
    }

//    @Bean
//    public HashedCredentialsMatcher hashedCredentialsMatcher() {
//        HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
//        //指定加密方式
//        credentialsMatcher.setHashAlgorithmName(AuthenConst.HASH_ALGORITHM_NAME);
//        //加密次数
//        credentialsMatcher.setHashIterations(AuthenConst.HASH_INTERACTIONS);
//        //此处的设置，true加密用的hex编码，false用的base64编码
//        credentialsMatcher.setStoredCredentialsHexEncoded(true);
//        return credentialsMatcher;
//    }

    @Bean
    public SessionManager sessionManager(){
        MySessionManager mySessionManager = new MySessionManager();
//        取消登陆跳转URL后面的jsessionid参数
        mySessionManager.setSessionIdUrlRewritingEnabled(false);
        mySessionManager.setSessionDAO(redisSessionDAO());
//        不过期
        mySessionManager.setGlobalSessionTimeout(-1);
        return mySessionManager;
    }

    @Bean
    public RedisManager redisManager(){
        RedisManager redisManager = new RedisManager();
        redisManager.setHost(shiroProperty.getRedis().getHost()+":"+shiroProperty.getRedis().getPort());
        redisManager.setDatabase(0);
        return redisManager;
    }

    @Bean
    public RedisSessionDAO redisSessionDAO(){
        RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
        redisSessionDAO.setRedisManager(redisManager());
        return redisSessionDAO;
    }
}
